package com.hundsun.epay.autosimu.internal;

import com.hundsun.epay.autosimu.api.IntrospectedChannel;
import com.hundsun.epay.autosimu.api.IntrospectedFieldControl;
import com.hundsun.epay.autosimu.api.IntrospectedTrade;
import com.hundsun.epay.autosimu.codegen.jfinal.JFinalIntrospectedChannelImpl;
import com.hundsun.epay.autosimu.config.Channel;
import com.hundsun.epay.autosimu.config.ControllerField;
import com.hundsun.epay.autosimu.config.ControllerResp;
import com.hundsun.epay.autosimu.config.PayCorporation;
import com.hundsun.epay.autosimu.config.Trade;
import com.hundsun.epay.autosimu.enums.SupportOperator;
import com.hundsun.epay.autosimu.internal.parse.EqualOperatorParser;
import com.hundsun.epay.autosimu.internal.parse.OperatorParser;

public class ObjectFactory {
	private ObjectFactory(){}
	
	public static Class<?> internalClassForName(String type) throws ClassNotFoundException{
		Class<?> answer = null;
		try {
			ClassLoader cl = Thread.currentThread().getContextClassLoader();
			answer = Class.forName(type, true, cl);
		} catch (Exception e) {
			// do nothing
		}
		if(answer == null){
			answer = Class.forName(type, true, ObjectFactory.class.getClassLoader());
		}
		return answer;
	}
	
	public static IntrospectedChannel createIntrospectedChannel(Channel channelConfig,
			PayCorporation payCorpConfig){
		String type = JFinalIntrospectedChannelImpl.class.getName();
		IntrospectedChannel answer = (IntrospectedChannel) createInternalObject(type);
		answer.setChannelConfig(channelConfig);
		answer.setPayCorpConfig(payCorpConfig);
		return answer;
	}
	
	public static Object createInternalObject(String type){
		Object answer;
		try {
			Class<?> clazz = internalClassForName(type);
			answer = clazz.newInstance();
		} catch (Exception e) {
			throw new RuntimeException(String.format("Cannot instantiate object of type %s", type), e);
		}
		
		return answer;
	}
	
	public static IntrospectedFieldControl createIntrospectedFieldControl(ControllerField fieldConfig ,Trade tradeConfig, Channel channelConfig, PayCorporation payCorpConfig){
		String type = DefaultIntrospectedFieldControl.class.getName();
		IntrospectedFieldControl answer = (IntrospectedFieldControl) createInternalObject(type);
		answer.setPayCorpConfig(payCorpConfig);
		answer.setChannelConfig(channelConfig);
		answer.setTradeConfig(tradeConfig);
		answer.setFieldConfig(fieldConfig);
		return answer;
	}
	
	public static IntrospectedTrade createIntrospectedTrade(Trade tradeConfig, Channel channelConfig, PayCorporation payCorpConfig){
		IntrospectedTrade answer = createIntrospectedTradeForValidation(tradeConfig);
		answer.setChannel(channelConfig);
		answer.setPayCorp(payCorpConfig);
		return answer;
	}
	
	public static IntrospectedTrade createIntrospectedTradeForValidation(Trade tradeConfig){
		String tradeType = tradeConfig.getType().getType();
		String type = null;
		type = DefaultIntrospectedTrade.class.getName();
		IntrospectedTrade answer = (IntrospectedTrade) createInternalObject(type);
		answer.setTrade(tradeConfig);
		return answer;
	}
	
	public static OperatorParser createOperatorParser(SupportOperator so){
		if(SupportOperator.EQUAL == so){
			return (OperatorParser) createInternalObject(EqualOperatorParser.class.getName());
		}else{
			throw new RuntimeException("Cannot instantiate parser.");
		}
	}
	
	public static ControlRespPackaging createControlRespPacking(ControllerResp resp){
		String type = ControlRespPackaging.class.getName();
		ControlRespPackaging packing = (ControlRespPackaging) createInternalObject(type);
		packing.setResp(resp);
		return packing;
	}
}
